package org.linlinjava.litemall.wxserver.web;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.systemConfig.GetRegionService;
import org.linlinjava.litemall.core.util.RegexUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.LitemallAddress;
import org.linlinjava.litemall.db.domain.LitemallRegion;
import org.linlinjava.litemall.db.service.LitemallAddressService;
import org.linlinjava.litemall.wxserver.annotation.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/wx/address")
public class WxAddressController extends GetRegionService {
    private final Log logger = LogFactory.getLog(WxAddressController.class);

    @Autowired
    private LitemallAddressService addressService;
    @Resource
    private RedisTemplate redisTemplate;
    @Autowired
    private PlatformTransactionManager txManager;


    /**
     * 用户收货地址列表
     *
     * @param userId 用户ID
     * @return 收货地址列表
     *   成功则
     *  {
     *      errno: 0,
     *      errmsg: '成功',
     *      data: xxx
     *  }
     *   失败则 { errno: XXX, errmsg: XXX }
     */
    @GetMapping("list")
    public Object list(@LoginUser Integer userId) {
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        String key="addressByUser"+userId;
        // 缓存存在
        boolean hasKey = redisTemplate.hasKey(key);
        if (hasKey) {
            // 从缓存中取
            List data= redisTemplate.opsForList().range(key, 0, -1);
            System.out.println("从缓存取");
            return ResponseUtil.ok(data);
        }else {
            Boolean mtype = false;
            List<LitemallAddress> addressList = addressService.queryByUid(userId,mtype);
            List<Map<String, Object>> addressVoList = new ArrayList<>(addressList.size());
            List<LitemallRegion> regionList = getLitemallRegions();
            for (LitemallAddress address : addressList) {
                Map<String, Object> addressVo = new HashMap<>(16);
                addressVo.put("id", address.getId());
                addressVo.put("name", address.getName());
                addressVo.put("mobile", address.getMobile());
                addressVo.put("isDefault", address.getIsDefault());
                String province= regionList.stream().filter(region->region.getId().equals(address.getProvinceId())).findAny().orElse(null).getName();
                String city =regionList.stream().filter(region->region.getId().equals(address.getCityId())).findAny().orElse(null).getName();
                String area =regionList.stream().filter(region->region.getId().equals(address.getAreaId())).findAny().orElse(null).getName();
                String addr = address.getAddress();
                String detailedAddress = province + city + area + " " + addr;
                addressVo.put("detailedAddress", detailedAddress);
                redisTemplate.opsForList().rightPushAll(key, addressVo);
                redisTemplate.expire(key,20, TimeUnit.MINUTES);
                addressVoList.add(addressVo);
            }
            System.out.println("查询库");
            return ResponseUtil.ok(addressVoList);
        }
    }

    /**
     * 收货地址详情
     *
     * @param userId 用户ID
     * @param id 收获地址ID
     * @return 收货地址详情
     *   成功则
     *  {
     *      errno: 0,
     *      errmsg: '成功',
     *      data:
     *        {
     *           id: xxx,
     *           name: xxx,
     *           provinceId: xxx,
     *           cityId: xxx,
     *           districtId: xxx,
     *           mobile: xxx,
     *           address: xxx,
     *           isDefault: xxx,
     *           provinceName: xxx,
     *           cityName: xxx,
     *           areaName: xxx
     *        }
     *  }
     *   失败则 { errno: XXX, errmsg: XXX }
     */
    @GetMapping("detail")
    public Object detail(@LoginUser Integer userId, Integer id) {
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        if(id == null){
            return ResponseUtil.badArgument();
        }

        LitemallAddress address = addressService.findById(id);
        if(address == null){
            return ResponseUtil.badArgumentValue();
        }
        List<LitemallRegion> regionList = getLitemallRegions();

        Map<Object, Object> data = new HashMap<>(16);
        if(address != null) {
            data.put("id", address.getId());
            data.put("name", address.getName());
            data.put("provinceId", address.getProvinceId());
            data.put("cityId", address.getCityId());
            data.put("districtId", address.getAreaId());
            data.put("mobile", address.getMobile());
            data.put("address", address.getAddress());
            data.put("isDefault", address.getIsDefault());
        }else{
            return ResponseUtil.fail();
        }
        String pname= regionList.stream().filter(region->region.getId().equals(address.getProvinceId())).findAny().orElse(null).getName();
        String cname =regionList.stream().filter(region->region.getId().equals(address.getCityId())).findAny().orElse(null).getName();
        String dname =regionList.stream().filter(region->region.getId().equals(address.getAreaId())).findAny().orElse(null).getName();

        data.put("provinceName", pname);
        data.put("cityName", cname);
        data.put("areaName", dname);
        return ResponseUtil.ok(data);
    }

    /**
     * 添加或更新收货地址
     *
     * @param userId 用户ID
     * @param address 用户收货地址
     * @return 添加或更新操作结果
     *   成功则 { errno: 0, errmsg: '成功' }
     *   失败则 { errno: XXX, errmsg: XXX }
     */
    @PostMapping("save")
    public Object save(@LoginUser Integer userId, @RequestBody LitemallAddress address) {
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        if(address == null){
            return ResponseUtil.badArgument();
        }

        // 测试收货手机号码是否正确
        String mobile = address.getMobile();
        if(!RegexUtil.isMobileExact(mobile)){
            return ResponseUtil.badArgument();
        }
        address.setMechanismType(false);
        // 开启事务管理
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus status = txManager.getTransaction(def);
        try{
            if(address.getIsDefault()){
                // 重置其他收获地址的默认选项
                addressService.resetDefault(userId);
            }
            String key="addressByUser"+userId;
            if (address.getId() == null || address.getId().equals(0)) {
                // 新增取货地址
                address.setMechanismType(false);
                address.setId(null);
                address.setAddTime(LocalDateTime.now());
                address.setUserId(userId);
                addressService.add(address);
            } else {
                address.setUserId(userId);
                address.setMechanismType(false);
                addressService.update(address);
            }
            while (redisTemplate.opsForList().size((key)) > 0){
                redisTemplate.opsForList().leftPop(key);
            }
        }    catch (Exception ex) {
            txManager.rollback(status);
            return ResponseUtil.fail(-1, "保存失败");
        }
        txManager.commit(status);

        return ResponseUtil.ok(address.getId());
    }

    /**
     * 删除收货地址
     *
     * @param userId 用户ID
     * @param address 用户收货地址
     * @return 删除结果
     *   成功则 { errno: 0, errmsg: '成功' }
     *   失败则 { errno: XXX, errmsg: XXX }
     */
    @PostMapping("delete")
    public Object delete(@LoginUser Integer userId, @RequestBody LitemallAddress address) {
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        if(address == null){
            return ResponseUtil.badArgument();
        }

        addressService.delete(address.getId());
        String key = "addressByUser"+userId;
        while (redisTemplate.opsForList().size((key)) > 0){
            redisTemplate.opsForList().leftPop(key);
        }
        return ResponseUtil.ok();
    }
}